using System;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ReactiveCode
{
    using Expressions;
    using Observables;

    [TestClass]
    public class ExceptionHandlingTests: ReactiveCodeTestClassBase
    {
        ReactiveExpression AssignmentWithException()
        {
            var state = new Variable<int>();
            var value = Observable.Throw<int>(new Exception());

            return Assign(state, value);
        }

        [TestMethod]
        [ExpectedException(typeof(ReactiveException))]
        public void ExceptionInAssignment()
        {
            var handle = Host.Call(AssignmentWithException(), false);

            bool exceptionInHost = false;
            bool exceptionInHandle = false;

            Host.UnhandledException += (s, e) =>
            {
                Assert.IsFalse(e.IsHandled);
                exceptionInHost = true;
            };
            handle.UnhandledException += (s, e) =>
            {
                Assert.IsFalse(e.IsHandled);
                Assert.IsFalse(exceptionInHost);
                exceptionInHandle = true;
            };

            try
            {
                handle.Enabled = true;
                Wait();
                Assert.Fail();
            }
            catch (ReactiveException)
            {
                Assert.IsTrue(exceptionInHost && exceptionInHandle);
                throw;
            }
            catch (Exception)
            {
                Assert.Fail();
            }
        }

        [TestMethod]
        public void HandledExceptionInAssignment()
        {
            var handle = Host.Call(AssignmentWithException(), false);

            bool handledException = false;
            handle.UnhandledException += (s, e) =>
            {
                e.SetHandled();
                handledException = true;
            };

            handle.Enabled = true;
            Wait();
            Assert.IsTrue(handledException);
        }
    }
}